#include "Nano100Series.h"
#include "Common.h"
#include "TouchSensor.h"
#include "GpioIrq.h"

enum touch_sensor_state_t {
	TOUCH_SENSOR_STATE_IDLE = 0,
	TOUCH_SENSOR_STATE_SLIDE,
};

static TouchSensorHandle brightness_plus_handle = NULL;
static TouchSensorHandle brightness_minus_handle = NULL;
static TouchSensorHandle volume_plus_handle = NULL;
static TouchSensorHandle volume_minus_handle = NULL;

static void TouchSensorHandleSlideLeft(uint32_t key_bits_new,
									TouchSensorHandle plus_handle,
									TouchSensorHandle minus_handle)
{
	static enum touch_sensor_state_t touch_sensor_state = TOUCH_SENSOR_STATE_IDLE;
	static uint32_t counter = 0;
	static uint32_t key_bits_old = 0;
	int key_head_index_old;
	int key_tail_index_old;
	int key_head_index_new;
	int key_tail_index_new;
	int i;
	
	counter++;

	if (key_bits_new) {
		LogDebug("\n Left [ ");
		if (key_bits_new & (0x01 << 0)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 1)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 2)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 3)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}
		LogDebug("]\n");
	}

	if (touch_sensor_state == TOUCH_SENSOR_STATE_IDLE) {
		if (key_bits_new) {
			counter = 0;
			touch_sensor_state = TOUCH_SENSOR_STATE_SLIDE;
			key_bits_old = key_bits_new;
		}
	} else {
		if (key_bits_new) {
			counter = 0;
			if (key_bits_new != key_bits_old) {
				for (i = 0; i <= (TOUCH_SENSOR_KEY_COUNT - 1); i++) {
	 				if (key_bits_old & (0x01 << i)) {
						key_head_index_old = i;
						break;
					}
				}

				for (i = TOUCH_SENSOR_KEY_COUNT - 1; i >= 0; i--) {
	 				if (key_bits_old & (0x01 << i)) {
						key_tail_index_old = i;
						break;
					}
				}

				for (i = 0; i <= (TOUCH_SENSOR_KEY_COUNT - 1); i++) {
	 				if (key_bits_new & (0x01 << i)) {
						key_head_index_new = i;
						break;
					}
				}

				for (i = TOUCH_SENSOR_KEY_COUNT - 1; i >= 0; i--) {
	 				if (key_bits_new & (0x01 << i)) {
						key_tail_index_new = i;
						break;
					}
				}

				LogDebug("key_head_index_old : %d\n", key_head_index_old);
				LogDebug("key_tail_index_old : %d\n", key_tail_index_old);
				LogDebug("key_head_index_new : %d\n", key_head_index_new);
				LogDebug("key_tail_index_new : %d\n", key_tail_index_new);

				if (key_head_index_new < key_head_index_old) {
					for (i = 0; i < (key_head_index_old - key_head_index_new); i++) {
						if (plus_handle) {
							(*plus_handle)();
						}
					}
				}

				if (key_tail_index_new > key_tail_index_old) {
					for (i = 0; i < (key_tail_index_new - key_tail_index_old); i++) {
						if (minus_handle) {
							(*minus_handle)();
						}
					}
				}
				key_bits_old = key_bits_new;
			}
		} else {
			counter++;
			if (counter >= 20) {
				touch_sensor_state = TOUCH_SENSOR_STATE_IDLE;
			}
		}
	}
}

static void TouchSensorHandleSlideRight(uint32_t key_bits_new,
									TouchSensorHandle plus_handle,
									TouchSensorHandle minus_handle)
{
	static enum touch_sensor_state_t touch_sensor_state = TOUCH_SENSOR_STATE_IDLE;
	static uint32_t counter = 0;
	static uint32_t key_bits_old = 0;
	int key_head_index_old;
	int key_tail_index_old;
	int key_head_index_new;
	int key_tail_index_new;
	int i;
	
	if (key_bits_new) {
		LogDebug("\n Right [ ");
		if (key_bits_new & (0x01 << 0)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 1)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 2)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}

		if (key_bits_new & (0x01 << 3)) {
			LogDebug("+ ");
		} else {
			LogDebug("  ");
		}
		LogDebug("]\n");
	}

	if (touch_sensor_state == TOUCH_SENSOR_STATE_IDLE) {
		if (key_bits_new) {
			counter = 0;
			touch_sensor_state = TOUCH_SENSOR_STATE_SLIDE;
			key_bits_old = key_bits_new;
		}
	} else {
		if (key_bits_new) {
			counter = 0;
			if (key_bits_new != key_bits_old) {
				for (i = 0; i <= (TOUCH_SENSOR_KEY_COUNT - 1); i++) {
	 				if (key_bits_old & (0x01 << i)) {
						key_head_index_old = i;
						break;
					}
				}

				for (i = TOUCH_SENSOR_KEY_COUNT - 1; i >= 0; i--) {
	 				if (key_bits_old & (0x01 << i)) {
						key_tail_index_old = i;
						break;
					}
				}

				for (i = 0; i <= (TOUCH_SENSOR_KEY_COUNT - 1); i++) {
	 				if (key_bits_new & (0x01 << i)) {
						key_head_index_new = i;
						break;
					}
				}

				for (i = TOUCH_SENSOR_KEY_COUNT - 1; i >= 0; i--) {
	 				if (key_bits_new & (0x01 << i)) {
						key_tail_index_new = i;
						break;
					}
				}

				LogDebug("key_head_index_old : %d\n", key_head_index_old);
				LogDebug("key_tail_index_old : %d\n", key_tail_index_old);
				LogDebug("key_head_index_new : %d\n", key_head_index_new);
				LogDebug("key_tail_index_new : %d\n", key_tail_index_new);

				if (key_head_index_new < key_head_index_old) {
					for (i = 0; i < (key_head_index_old - key_head_index_new); i++) {
						if (plus_handle) {
							(*plus_handle)();
						}
					}
				}

				if (key_tail_index_new > key_tail_index_old) {
					for (i = 0; i < (key_tail_index_new - key_tail_index_old); i++) {
						if (minus_handle) {
							(*minus_handle)();
						}
					}
				}
				key_bits_old = key_bits_new;
			}
		} else {
			counter++;
			if (counter >= 20) {
				touch_sensor_state = TOUCH_SENSOR_STATE_IDLE;
			}
		}
	}
}

/* 100 Hz, 10 ms */
void TMR2_IRQHandler(void)
{
	uint32_t key_bits_new;

	key_bits_new = 0;
	if (!TOUCH_SENSOR_LEFT_KEY0_PIN) {
		key_bits_new |= (0x01 << 0);
	}

	if (!TOUCH_SENSOR_LEFT_KEY1_PIN) {
		key_bits_new |= (0x01 << 1);
	}

	if (!TOUCH_SENSOR_LEFT_KEY2_PIN) {
		key_bits_new |= (0x01 << 2);
	}

	if (!TOUCH_SENSOR_LEFT_KEY3_PIN) {
		key_bits_new |= (0x01 << 3);
	}

	TouchSensorHandleSlideLeft(key_bits_new, volume_plus_handle, volume_minus_handle);

	key_bits_new = 0;
	if (!TOUCH_SENSOR_RIGHT_KEY0_PIN) {
		key_bits_new |= (0x01 << 0);
	}

	if (!TOUCH_SENSOR_RIGHT_KEY1_PIN) {
		key_bits_new |= (0x01 << 1);
	}

	if (!TOUCH_SENSOR_RIGHT_KEY2_PIN) {
		key_bits_new |= (0x01 << 2);
	}

	if (!TOUCH_SENSOR_RIGHT_KEY3_PIN) {
		key_bits_new |= (0x01 << 3);
	}
	TouchSensorHandleSlideRight(key_bits_new, brightness_plus_handle, brightness_minus_handle);

    TIMER_ClearIntFlag(TIMER2);
}

static void Timer2Init(void)
{
    TIMER_Open(TIMER2, TIMER_PERIODIC_MODE, 100);
    TIMER_EnableInt(TIMER2);
    NVIC_EnableIRQ(TMR2_IRQn);
    TIMER_Start(TIMER2);
}

void TouchSensorInit(void)
{
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_LEFT_KEY0_PORT, TOUCH_SENSOR_LEFT_KEY0_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_LEFT_KEY1_PORT, TOUCH_SENSOR_LEFT_KEY1_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_LEFT_KEY2_PORT, TOUCH_SENSOR_LEFT_KEY2_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_LEFT_KEY3_PORT, TOUCH_SENSOR_LEFT_KEY3_BIT);

	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_RIGHT_KEY0_PORT, TOUCH_SENSOR_RIGHT_KEY0_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_RIGHT_KEY1_PORT, TOUCH_SENSOR_RIGHT_KEY1_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_RIGHT_KEY2_PORT, TOUCH_SENSOR_RIGHT_KEY2_BIT);
	GPIO_ENABLE_PULL_UP(TOUCH_SENSOR_RIGHT_KEY3_PORT, TOUCH_SENSOR_RIGHT_KEY3_BIT);

	Timer2Init();
}

void TouchSensorDisable(void)
{
	NVIC_DisableIRQ(TMR2_IRQn);
}

void TouchSensorEnable(void)
{
	NVIC_EnableIRQ(TMR2_IRQn);
}

void TouchSensorSetHandleBrightnessPlus(TouchSensorHandle handle)
{
	brightness_plus_handle = handle;
}

void TouchSensorSetHandleBrightnessMinus(TouchSensorHandle handle)
{
	brightness_minus_handle = handle;
}

void TouchSensorSetHandleVolumePlus(TouchSensorHandle handle)
{
	volume_plus_handle = handle;
}

void TouchSensorSetHandleVolumeMinus(TouchSensorHandle handle)
{
	volume_minus_handle = handle;
}
